package com.zb.automation.service.impl.swagger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.zb.automation.common.Constant;
import com.zb.automation.enums.ParamTypeEnum;
import com.zb.automation.enums.RequestMethodEnum;
import com.zb.automation.model.response.AnalysisSwaggerDTO;
import com.zb.automation.model.response.JsonParamsDTO;
import com.zb.automation.model.request.ReqSwaggerDTO;
import com.zb.automation.model.swagger.SwaagerDefinitionsDTO;
import com.zb.automation.model.swagger.SwaggerDTO;
import com.zb.automation.model.swagger.SwaggerParameterDTO;
import com.zb.automation.model.swagger.SwaggerPathDTO;
import com.zb.automation.util.HttpRequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author ZhangBin
 * @Data 2022/7/23 14:37
 * @Description 解析swagger
 */
@Slf4j
public class SwaggerAnalysis {

    private final static String $REF = "$ref";

    private final static String PARAMETER_NAME = "parameterName";

    private final static String SUCCESS = "200";

    private final static String DEFINITIONS = "#/definitions/";
    private final static String TYPE = "type";

    private final static String DESCRIPTION = "description";

    private final static String FORMAT = "format";

    private final static String ITEMS = "items";

    private final static String PARAM_TYPE_STR="int,Int;string,String;long,Long;float,Float;double,Double;boolean,Boolean;bigdecimal,Bigdecimal;byte,Byte;number,Number;hashmap,HashMap;list,List;null,Null;array,Array";

    public static List<AnalysisSwaggerDTO> analysisSwagger2Tree(String path) {
        log.info("=========解析swagger地址 start===========");
        //http请求查询swagger信息
        List<ReqSwaggerDTO> apiBOList = analysisSwagger(path);
        if (CollectionUtils.isEmpty(apiBOList)) {
            throw new RuntimeException("地址解析错误，请求输入正确地址");
        }
        Map<String, List<ReqSwaggerDTO>> apiBOMap = apiBOList.stream().collect(Collectors.groupingBy(ReqSwaggerDTO::getPathType));
        List<AnalysisSwaggerDTO> voList = new ArrayList<>();
        AnalysisSwaggerDTO resVO;
        for (Map.Entry<String, List<ReqSwaggerDTO>> entry : apiBOMap.entrySet()) {
            resVO = new AnalysisSwaggerDTO();
            resVO.setPathType(entry.getKey());
            for (ReqSwaggerDTO swaggerApiBO : entry.getValue()) {
                //设置默认值
                for (JsonParamsDTO jsonParam : swaggerApiBO.getReqParamt()) {
                    jsonParam.setParamDesc(StringUtils.isEmpty(jsonParam.getParamDesc()) ? jsonParam.getParamName() : jsonParam.getParamDesc());
                    jsonParam.setParamType(StringUtils.isEmpty(jsonParam.getParamType()) ? ParamTypeEnum.OBJECT.getCode() : exchangeParamType(jsonParam.getParamType()));
                }
                //设置默认值
                for (JsonParamsDTO jsonParam : swaggerApiBO.getResParamt()) {
                    jsonParam.setParamDesc(StringUtils.isEmpty(jsonParam.getParamDesc()) ? jsonParam.getParamName() : jsonParam.getParamDesc());
                    jsonParam.setParamType(StringUtils.isEmpty(jsonParam.getParamType()) ? ParamTypeEnum.OBJECT.getCode() : exchangeParamType(jsonParam.getParamType()));
                }
            }
            resVO.setApiBOS(entry.getValue());
            voList.add(resVO);
        }
        //解析swagger
        return voList;
    }

    public static List<ReqSwaggerDTO> analysisSwagger2List(String path){
        List<ReqSwaggerDTO> apiBOList = analysisSwagger(path);
        if (CollectionUtils.isEmpty(apiBOList)) {
            throw new RuntimeException("地址解析错误，请求输入正确地址");
        }
        Map<String, List<ReqSwaggerDTO>> apiBOMap = apiBOList.stream().collect(Collectors.groupingBy(ReqSwaggerDTO::getPathType));
        int id = 0;
        List<ReqSwaggerDTO> list = new ArrayList<>();
        for (Map.Entry<String, List<ReqSwaggerDTO>> entry : apiBOMap.entrySet()) {
            int parentId = ++id;
            ReqSwaggerDTO reqSwaggerDTO = new ReqSwaggerDTO();
            reqSwaggerDTO.setParentId(0);
            reqSwaggerDTO.setId(parentId);
            reqSwaggerDTO.setPathType(entry.getKey());
            reqSwaggerDTO.setPathName(entry.getKey());
            list.add(reqSwaggerDTO);
            for (ReqSwaggerDTO reqSwagger : entry.getValue()) {
                ReqSwaggerDTO reqSwaggerChild = reqSwagger;
                reqSwaggerChild.setParentId(parentId);
                reqSwaggerChild.setId(++id);
                list.add(reqSwaggerChild);
                //设置默认值
                for (JsonParamsDTO jsonParam : reqSwagger.getReqParamt()) {
                    jsonParam.setParamDesc(StringUtils.isEmpty(jsonParam.getParamDesc()) ? jsonParam.getParamName() : jsonParam.getParamDesc());
                    jsonParam.setParamType(StringUtils.isEmpty(jsonParam.getParamType()) ? ParamTypeEnum.OBJECT.getCode() : exchangeParamType(jsonParam.getParamType()));
                }
                //设置默认值
                for (JsonParamsDTO jsonParam : reqSwagger.getResParamt()) {
                    jsonParam.setParamDesc(StringUtils.isEmpty(jsonParam.getParamDesc()) ? jsonParam.getParamName() : jsonParam.getParamDesc());
                    jsonParam.setParamType(StringUtils.isEmpty(jsonParam.getParamType()) ? ParamTypeEnum.OBJECT.getCode() : exchangeParamType(jsonParam.getParamType()));
                }
            }

        }
        return list;
    }

    private static List<ReqSwaggerDTO> analysisSwagger(String url) {
        String req = HttpRequestUtil.sendGet(url, null);
        if (Objects.isNull(req)) {
            throw new RuntimeException( "地址解析错误，请求输入正确地址");
        }
        String json = req.replace($REF, PARAMETER_NAME);
        SwaggerDTO swaggerDTO;
        try {
            swaggerDTO = JSON.parseObject(json, new TypeReference<SwaggerDTO>() {
            });
        } catch (Exception e) {
            throw new RuntimeException("请输入正确的Swagger api-docs地址");
        }
        if (Objects.isNull(swaggerDTO)) {
            throw new RuntimeException("请输入正确的Swagger api-docs地址");
        }
        List<ReqSwaggerDTO> list = new ArrayList<>();
        ReqSwaggerDTO swaggerApiBO;
        //所以参数
        Map<String, SwaagerDefinitionsDTO> definitions = swaggerDTO.getDefinitions();
        for (Map.Entry<String, Map<String, SwaggerPathDTO>> entry : swaggerDTO.getPaths().entrySet()) {
            swaggerApiBO = new ReqSwaggerDTO();
            Map<String, SwaggerPathDTO> pathMap = entry.getValue();
            //post请求
            RequestMethodEnum requestMethodEnum = null;
            for (Map.Entry<String, SwaggerPathDTO> entryPuth : pathMap.entrySet()) {
                if (requestMethodEnum.getInstance(entryPuth.getKey()) != null) {
                    requestMethodEnum = requestMethodEnum.getInstance(entryPuth.getKey());
                    break;
                }
            }
            if (null == requestMethodEnum) {
                continue;
            }
            SwaggerPathDTO post = pathMap.get(requestMethodEnum.getType());
            //請求方式
            swaggerApiBO.setRequestWay(requestMethodEnum.getDesc());
            //接口名称
            swaggerApiBO.setPathName(post.getSummary() == null ? Constant.EMPTY_STRING : post.getSummary());
            //获取方法名称
            swaggerApiBO.setMethodName(entry.getKey().substring(entry.getKey().lastIndexOf(Constant.SLASH) + 1));
            //接口地址
            swaggerApiBO.setPath(entry.getKey());
            //接口类定义
            swaggerApiBO.setPathType(post.getTags().get(0));
            //请求参数
            List<SwaggerParameterDTO> parameters = post.getParameters();
            //响应参数
            Map<String, SwaggerParameterDTO> responseMap = post.getResponses();
            List<JsonParamsDTO> reqParamt = new ArrayList<>();
            //解析入参
            if (null == parameters || parameters.get(0) == null) {
                System.out.println(JSON.toJSON(post));
            } else {
                getReqParameter(parameters.get(0), definitions, reqParamt);
            }
            //设置入参
            swaggerApiBO.setReqParamt(reqParamt);

            //成功响应参数
            List<JsonParamsDTO> resParamt = new ArrayList<>();
            SwaggerParameterDTO parameterBO = responseMap.get(SUCCESS);
            getReqParameter(parameterBO, definitions, resParamt);
            swaggerApiBO.setResParamt(resParamt);
            list.add(swaggerApiBO);
        }
        return list;
    }

    private static void getReqParameter(SwaggerParameterDTO reqParemet, Map<String, SwaagerDefinitionsDTO> definitions, List<JsonParamsDTO> reqList) {
        if (reqParemet == null) {
            return;
        }
        JsonParamsDTO infoParamsBO;
        if (reqParemet != null & (reqParemet.getSchema() == null || reqParemet.getSchema().getParameterName() == null)) {
            infoParamsBO = new JsonParamsDTO();
            infoParamsBO.setParamType(reqParemet.getType());
            infoParamsBO.setParamName(reqParemet.getName());
            reqList.add(infoParamsBO);
            return;
        }
        String $ref = reqParemet.getSchema().getParameterName().replace(DEFINITIONS, Constant.EMPTY_STRING);
        SwaagerDefinitionsDTO definitionsBO = definitions.get($ref);
        if (null == definitionsBO) {
            return;
        }
        //入参参数
        Map<String, Map<String, Object>> reqParmeter = definitionsBO.getProperties();
        reqList.addAll(getChild(reqParmeter, definitions, 0));

    }
    private static List<JsonParamsDTO> getChild(Map<String, Map<String, Object>> reqParmeter, Map<String, SwaagerDefinitionsDTO> definitions, int count) {
        List<JsonParamsDTO> list = new ArrayList<>();
        if (null == reqParmeter) {
            return list;
        }
        for (Map.Entry<String, Map<String, Object>> parmeter : reqParmeter.entrySet()) {
            JsonParamsDTO jsonParamsDTO = new JsonParamsDTO();
            jsonParamsDTO.setParamName(parmeter.getKey());
            for (Map.Entry<String, Object> parmeterType : parmeter.getValue().entrySet()) {
                if (TYPE.equals(parmeterType.getKey())) {
                    jsonParamsDTO.setParamType(String.valueOf(parmeterType.getValue()));
                } else if (DESCRIPTION.equals(parmeterType.getKey())) {
                    jsonParamsDTO.setParamDesc(String.valueOf(parmeterType.getValue()));
                } else if (FORMAT.equals(parmeterType.getKey())) {
                    //暂时没用
                } else if (ITEMS.equals(parmeterType.getKey())) {
                    Object parameterName = ((com.alibaba.fastjson.JSONObject) parmeterType.getValue()).get(PARAMETER_NAME);
                    if (parameterName != null) {
                        String parameterName1 = (String) parameterName;
                        String $ref = parameterName1.replace(DEFINITIONS, Constant.EMPTY_STRING);
                        SwaagerDefinitionsDTO definitionsBO = definitions.get($ref);
                        if (null == definitionsBO) {
                            return list;
                        }
                        //入参参数的key
                        reqParmeter = definitionsBO.getProperties();
                        //设置子类
                        count++;
                        if (count >= 2) {
                            continue;
                        }
                        jsonParamsDTO.setChildren(getChild(reqParmeter, definitions, count));
                    } else {
                        if (null == parmeterType.getValue()) {
                            continue;
                        }
                        JSONObject json = JSON.parseObject(JSON.toJSONString(parmeterType.getValue()));
                        String type = json.getString(TYPE);
                        if (null != type) {
                            jsonParamsDTO.setExampleValue(type);
                        }
                    }

                } else {
                    //这里代表有子类
                    if (!JSON.toJSONString(parmeterType.getKey()).contains(PARAMETER_NAME)) {
                        continue;
                    }
                    if (parmeterType.getValue() == null) {
                        return list;
                    }
                    String $ref = parmeterType.getValue().toString().replace(DEFINITIONS, Constant.EMPTY_STRING);
                    SwaagerDefinitionsDTO definitionsBO = definitions.get($ref);
                    if (null == definitionsBO) {
                        return list;
                    }
                    //入参参数的key
                    reqParmeter = definitionsBO.getProperties();
                    //设置子类
                    jsonParamsDTO.setChildren(getChild(reqParmeter, definitions, count));
                }
            }
            list.add(jsonParamsDTO);
        }
        return list;
    }
    private static String exchangeParamType(String orgParamType){
        String targetParamType = "";
        if(!StringUtils.isEmpty(PARAM_TYPE_STR)){
            String[] paramTypeArray=PARAM_TYPE_STR.split(Constant.SEMICOLON);
            List<String> paramTypeList= Arrays.asList(paramTypeArray);
            for(String tempParamType:paramTypeList){
                String[] targetParamTypeArray=tempParamType.split(Constant.COMMA);
                if(targetParamTypeArray[0].equalsIgnoreCase(orgParamType)){
                    targetParamType=targetParamTypeArray[1];
                    break;
                }
            }
        }
        return targetParamType;
    }
}
